<?php
/**
 * This class implements a connection to del.icio.us
 *
 * @author Thomas Kappel
 * @copyright Copyright (c) 2008
 * @version $Id: Abstract.php 1877 2008-02-19 18:09:30Z tkappel $
 */

function aboutWong() {
  return array(
    "name"    => "Mister Wong"
  );
}

class Wong extends Network_Abstract implements findContactsOfContacts {
  public $_Name            = "Wong";   // string:          name of the network
  public $user_id          = 0;       // string:          user id within the network
  public $me               = false;   // array:           all information about the user(account) himself 
  public $contacts         = false;   // array of arrays: data of contacts 
  public $username         = false;
  public $server_addr      = "http://www.mister-wong.de";

  public $activation_link  = false;   // string: url of the login page (optional)
  
  protected static $_instance  = null;
  
  public function __construct($account = false) {
    $this->NetworkName="Wong";
    $this->account = $account ? $account : false;
    self::$_instance = $this;
  }

  public function supports($method) {
    switch($method) {
      case "find_friends_of_friends"         : return true;
      case "multiple_accounts"               : return false; // one person should have only one account 
      case "require_requests_for_friendship" : return true;  // no need to send these messages
      case "save_friends_to_network"         : return false;
      case "search_members"                  : return false; // find account of a person you already know from other networks
      case "disconnect"                      : return false;
      default                                : return false;
    }
  }
  
  /*
   * @returns URL of the Social Network Service
   */  
  public function getServiceHomepage() {
    return "http://www.mister-wong.de";
  }

  /*
   * @returns associative array of arrays:
   *  "mandatory" => required fields for logging in (for example: "uri", "user", "pass")
   *  "optional"  => some more allowed fields
   */  
  public function getAccountingRequirements() {
    return array(
      "mandatory" => array("user"),
      "optional"  => array()
    );
  }

  public function require_connect_button() {
    return false;
  }

  public function search($contact) {
    // still does not work 
    $method = "buddysearch/";
    $parameters = array(
      "user_forename" => $contact['givenname'],
      "user_surname"  => $contact['family_name'],
    );
    $snippet  = $this->post_request($method, $parameters);
    if(!$snippet) return false;
    $start   = strpos($snippet, 'Neue Suche?');
    $length  = strpos($snippet, '<div id="middlebox">')-$start;
    $snippet = substr($snippet, $start, $length);
    $usernames = array();

    while($start = strpos($snippet, '<a href="http://www.mister-wong.de/user/')) {
      $snippet     = substr($snippet, $start + 40);
      $usernames[] = substr($snippet, 0, strpos($snippet, '/">'));
    }

    if(!sizeof($usernames)) return false;
    $results = array();
    foreach($usernames as $username) $results[]=$this->fetchContact($username);
    return $this->contacts[$username];
  }
  
  /*
   * establishes connection to the network
   * 
   * @param: URI, username, password (all optional, depending on the network)
   * @returns: information about the user or false on error
   */
  public function connect($URI="", $user="", $pass="") {
    //if(!strlen($user)) return false;
    $frontController = Zend_Controller_Front::getInstance();
    $request   = $frontController->getRequest();
    if($request->get('password')) $pass = $request->get('password');
    $reload = false;
    if(!strlen($pass)) {
      $template  = "enter_password";
      $message   = "enter";
      $code      = 401;
    } else {
      $result = $this->post_request("index.php?action=login",array('user_name' => $this->account["accountName"], 'user_password' => $pass, 'idd'=>'', 'login'=>'Login'));
      if(false === strpos($result, 'logout')) {
        $template  = "enter_password";
        $message   = "re_enter";
        $code      = 401;
      } else {
        // i got it
        $this->username = $this->account["accountName"];
        $template = "message";
        $message  = "OK.";
        $code     = 200;
        $reload   = true;
      }
    }
    // return results
    return array(
      "code"        => $code,
      "message"     => $message,
      "template"    => $template,
      //"action"      => $action,
      "reload"      => $reload,
      "user"        => $user
    );
  }

  /*
   * @returns true if connection is already established
   */
  public function connected() {
    return true;
    $result = $this->post_request("",array());
    return (false === strpos($result, 'logout')) ? false : true;
  }

  /*
   * close connection
   * 
   * @returns: boolean (true on success)
   */
  public function disconnect() {}
  
  /*
   * @returns: array of arrays holding fetchable information of all contacts
   */
  public function fetchContacts() {
    $accountName = $this->account["accountName"];
    if(!$this->account["accountName"]) $accountName = $this->accountName;
//    $contacts = $this->call_method("fetchcontacts", $accountName);
    $xml = $this->post_request("user/".$accountName."/?profile", array());

    // puzzle the required snipplet ;-)
    $start  = strpos($xml,'<ul id="friendlist">')+20;
    $xml = substr($xml,$start);
    $end    = strpos($xml,'</ul>');
    $xml = substr($xml,0,$end);
    $plain = trim(strip_tags($xml)); // containing usernames and whitespaces
    $usernames = preg_split('/[\s,]+/',$plain); 
    
    $max_contacts = 100;
    $counter = 1;
    return $usernames;
    /*
    foreach($usernames as $username) {
      $this->fetchContact($username);
      $counter++;
      if($counter>$max_contacts) break;
    }
    return $this->contacts;
    */
  }
  
  /**
   * @param: id of a contact
   * @return: standardised associative array of information about the user
   *           - foaf attributes
   *           - one element with the key "full_data" contains all fetchable information
   * @return associative array or false on error
   */
  function fetchContact($username) {
//    $contact = $this->call_method("fetchcontact",$uid);
    $xml = $this->post_request("user/".$username."/?profile", array());

    $this->contacts[$username]=array("accountName" => $username);
    
    // puzzle the required snipplet ;-)
    
    // find the user name
    $title = substr($xml, strpos($xml,'<title>')+7);
    $title = substr($title, 0, strpos($title,' |'));

    $separator_pos = strpos($title, ' - ');
    if($separator_pos) { // Name hinterlegt
      $this->contacts[$username]["name"] = trim(substr($title,0,$separator_pos));
      $nick = str_replace('&quot;', '', trim(substr($title,$separator_pos+2)));
      $this->contacts[$username]["nick"] = $nick;
      $this->contacts[$username]["accountName"] = $nick;
    } else {
      $nick = str_replace('&quot;', '', trim($title));
      $this->contacts[$username]["name"] = $nick;
      $this->contacts[$username]["nick"] = $nick;
      $this->contacts[$username]["accountName"] = $nick;
    }
    
    // find avatar
    $start = strpos ($xml, '<a href="./user/'.$username.'/"><img');
    if($start !== false) {
      $start+=strlen('<a href="./user/'.$username.'/"><img');
      $avatar = trim(substr($xml, $start));
      $start = strpos($avatar, 'src="')+5;
      $avatar = trim(substr($avatar, $start));
      $this->contacts[$username]["thumbnail"] = 'http://www.mister-wong.de/' . trim(substr($avatar,0,strpos($avatar, '"')));
    }

    // find optional data
    $start  = strpos($xml,'<h5>Profil</h5><ul>');

    if($start !== false) {
      $start+=19;
      $optional_data = substr($xml,$start);
      $end = strpos($optional_data,'</ul></div>');
      $optional_data = explode("<li>",substr($optional_data,0,$end));
      foreach($optional_data as $data) {
        if(!strlen($data) || '</ul><ul' == substr($data,0,8)) continue;
        $data = substr($data, 0, strpos($data, '</li>'));
        $separator_pos = strpos($data, ':');
        $type = trim(substr($data, 0, $separator_pos));
        $value = trim(substr($data, $separator_pos+1));
        switch($type) {
          case "Vorname":
            $this->contacts[$username]["givenname"] = $value;
            break;
          case "Nachname":
            $this->contacts[$username]["family_name"] = $value;
            break;
          case "Homepage":
            $this->contacts[$username]["homepage"] = strip_tags($value);
            break;
          case "Messenger": // allow more than one value
            $messenger_parts = explode(',',$value);
            foreach($messenger_parts as $messenger) {
              $messenger_network = trim(strip_tags($messenger));
              switch($messenger_network) { // currently ICQ is the only messenger network supported by both Mister Wong and FOAF
                case "ICQ":
                  $icq = substr($messenger, strpos($messenger, "\"")+1);
                  $icq = substr($messenger, 0, strpos($messenger, "\""));
                  if(is_int($icq)) $this->contacts[$username]["icqChatID"] = $icq;
                  break;
              }
            }
            break;
          case "Social Networks": // allow more than one value, ignore unsupported networks
            // at this moment no network is supported by both Mister Wong and Socializr
            break;
        }
      }
    }
/*
    if($contact!==false) {
      if(isset($contact["depiction"]) && strlen($contact["depiction"])) $this->contacts[$uid]["depiction"] = $contact["depiction"];
      if(isset($contact["homepage"])  && strlen($contact["homepage"]))  $this->contacts[$uid]["homepage"]  = $contact["homepage"];
      if(isset($contact["name"])      && strlen($contact["name"]))      $this->contacts[$uid]["name"]      = $contact["name"];
      if(isset($contact["nick"])      && strlen($contact["nick"]))      $this->contacts[$uid]["nick"]      = $contact["nick"];
    } */
    return $this->contacts[$username];
  }

  /**
   * @param: id of a contact
   * @return: array of user ids of contacts of the user
   * @return false on error 
   */ 
  public function fetchContactsOfContacts($uid) {
//    $contacts = $this->call_method("fetchcontacts", $accountName);
    $xml = $this->post_request("user/".$uid."/?profile", array());

    // puzzle the required snipplet ;-)
    $start  = strpos($xml,'<ul id="friendlist">')+20;
    $xml = substr($xml,$start);
    $end    = strpos($xml,'</ul>');
    $xml = substr($xml,0,$end);
    $plain = trim(strip_tags($xml)); // containing usernames and whitespaces
    $usernames = preg_split('/[\s,]+/',$plain); 
    
    $max_contacts = 100;
    $counter = 1;
    foreach($usernames as $username) {
      $this->fetchContact($username);
      $counter++;
      if($counter>$max_contacts) break;
    }
    return $this->contacts;
    
  }

  /**
   * @param: contact information (as returned by fetchContact())
   * @return: unique identifier of this account within the network
   */
  public function getAccountIdentifier($contact) {
    return $contact["accountName"];
  }

  /**
   * @return object: instance of this class
   */
  public static function getInstance() {
    if (null === self::$_instance) return false;
    return self::$_instance;
  }

  /**
   * @param   string: account name 
   * @param   string: another account name 
   * @return boolean: true, if the contacts are contacts of each other
   */
  public function areContacts($contact1, $contact2) {
    return false;
  }
  
  private function create_post_string($method, $params) {
    $params['method'] = $method;
 //   $params['session_key'] = $this->session_key;
 //   $params['api_key'] = $this->api_key;
 //   $params['call_id'] = microtime(true);
 //   if ($params['call_id'] <= $this->last_call_id) {
 //     $params['call_id'] = $this->last_call_id + 0.001;
 //   }
 //   $this->last_call_id = $params['call_id'];
    $post_params = array();
    foreach ($params as $key => &$val) {
      if (is_array($val)) $val = implode(',', $val);
      $post_params[] = $key.'='.urlencode($val);
    }
    return implode('&', $post_params);
  }

  public function post_request($method, $params) {

    $post_string = $this->create_post_string($method, $params);

    if (function_exists('curl_init')) {
      // Use CURL if installed...
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $this->server_addr."/".$method);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
       curl_setopt($ch, CURLOPT_VERBOSE, 0);
       curl_setopt($ch, CURLOPT_COOKIEJAR, "curl_cookies.txt");
       curl_setopt($ch, CURLOPT_COOKIEFILE, "curl_cookies.txt"); 
      curl_setopt($ch, CURLOPT_USERAGENT, 'No Mozilla although open source (curl) ' . phpversion());
      $result = curl_exec($ch);
      curl_close($ch);
    } else {
      // Non-CURL based version...
      $context =
        array('http' =>
              array('method' => 'POST',
                    'header' => 'Content-type: application/x-www-form-urlencoded'."\r\n".
                                'User-Agent: No Mozilla although open source (non-curl) '.phpversion()."\r\n".
                                'Content-length: ' . strlen($post_string),
                    'content' => $post_string));
      $contextid=stream_context_create($context);
      $sock=fopen($this->server_addr."/".$method, 'r', false, $contextid);
      if ($sock) {
        $result='';
        while (!feof($sock))
          $result.=fgets($sock, 4096);
        fclose($sock);
      }
    }
    return $result;
  }
}
?>
